import BLE_DATA from '../chaoliyuan/bleData.js';
import state from './state.js';

class ProtocolManager {
	constructor() {
		this.state = state;
	}

	/**
	 * 写入二进制数据到BLE特征值
	 * @param {ArrayBuffer} value - 要写入的二进制数据
	 * @param {Function} callback - 写入完成后的回调函数
	 */
	WriteBase(value, callback) {
		const {
			deviceId,
			serviceId,
			characteristicId,
			state
		} = getApp().globalData.bleObj;
		if (!state) {
			console.log('蓝牙未连接');
			return;
		}
		uni.writeBLECharacteristicValue({
			deviceId,
			serviceId,
			characteristicId,
			value,
			success: (res) => {
				if (res.errCode === 0 || res.errno === 0) {
					callback?.(res);
				} else {
					console.error('写入二进制失败', res);
				}
			},
			fail: (res) => {
				console.error('写入二进制失败', res);
			}
		});
	}

	/**
	 * CRC16 Modbus 计算
	 * @param {string} str - 十六进制字符串
	 * @returns {string} CRC16 校验码
	 */
	crc16Modbus(str) {
		const byteArray = [];
		for (let i = 0; i < str.length; i += 2) {
			byteArray.push(parseInt(str.substr(i, 2), 16));
		}
		let sum = 0;
		for (let i = 0; i < byteArray.length; i++) {
			sum += byteArray[i]; // 累加每个字节
		}
		return ((~sum + 1) & 0xFF).toString(16).padStart(2, '0'); // 取反加1后取低8位
	}


	/**
	 * 发送指令，不加2字节校验位
	 * @param {string} cmd - 指令字符串
	 * @param {Function} callback - 发送完成后的回调函数
	 */
	sendCommand(cmd, callback) {
		cmd = cmd.trim();
		const typedArray = new Uint8Array(cmd.match(/[\da-f]{2}/gi).map(h => parseInt(h, 16)));
		this.WriteBase(typedArray.buffer, callback);
	}

	/**
	 * 将 ArrayBuffer 转换为十六进制字符串
	 * @param {ArrayBuffer} buffer - ArrayBuffer 对象
	 * @returns {string} 十六进制字符串
	 */
	ab2hex(buffer) {
		return Array.prototype.map.call(new Uint8Array(buffer),
			bit => ('00' + bit.toString(16)).slice(-2)).join('');
	}


	/**
	 * 将数字转换为大端模式的十六进制字符串
	 * @param {number} num - 数字
	 * @returns {string} 十六进制字符串
	 */
	bufferToHex(num) {
		const buffer = new ArrayBuffer(2);
		const view = new DataView(buffer);
		view.setUint16(0, num, false); // 大端模式
		return Array.from(new Uint8Array(buffer))
			.map(byte => byte.toString(16).padStart(2, '0'))
			.join('')
			.toUpperCase();
	}

	/**
	 * 解包数据
	 * @param {string} str - 十六进制字符串
	 */
	solutionData(str, readValue) {
		let funCode = str.substr(8, 2) // 解析功能码
		let leftStr = str.substring(10, str.length)
		switch (funCode) {
			case '12':
				//为电池组状态标志
				let tempStatus = leftStr.substr(0, 8)
				for (var i = 0; i < 4; i++) {
					let bitStr = tempStatus.substr(i, 2);
					const vArray = this.hexToBitsFast(bitStr).split('').reverse();
					if (i === 0) {
						readValue['status1'] = getState1(vArray)
					}
					if (i === 1) {
						readValue['status2'] = getState2(vArray)
					}
					if (i === 2) {
						readValue['status3'] = getState3(vArray)
					}
					if (i === 3) {
						readValue['status4'] = getState4(vArray)
					}
				}
				leftStr = leftStr.substring(8, leftStr.length)
				//电流
				let CurCadcStr = leftStr.substr(0, 4)
				readValue['CurCadc'] = parseInt(this.reChangeStr(CurCadcStr) || '0', 16) * 0.1
				leftStr = leftStr.substring(4, leftStr.length)
				//电池组
				readValue['VCellNum'] = parseInt(leftStr.substr(0, 2) || '0', 16)
				leftStr = leftStr.substring(2, leftStr.length)
				let VCells = []
				let VCellNum = readValue['VCellNum'] * 1
				let tempCellStr = leftStr.substr(0, VCellNum * 4)
				for (var i = 0; i < VCellNum; i++) {
					let cellStr = tempCellStr.substr(i * 4, 4);
					VCells.push(parseInt(this.reChangeStr(cellStr) || '0', 16))
				}
				//电芯电压 mV
				readValue['VCell'] = VCells
				leftStr = leftStr.substring(VCellNum * 4, leftStr.length)

				//JH 开启平衡
				readValue['JH'] = leftStr.substr(0, VCellNum / 8 * 2)
				leftStr = leftStr.substring(VCellNum / 8 * 2, leftStr.length)

				//电芯温感数量
				readValue['DXWG'] = parseInt(leftStr.substr(0, 2) || '0', 16)
				leftStr = leftStr.substring(2, leftStr.length)

				//电芯温感温度
				let DTemps = []
				let DXWGSize = readValue['DXWG'] * 1
				let DXWGStr = leftStr.substr(0, 2 * DXWGSize)
				for (var i = 0; i < DXWGSize; i++) {
					DTemps.push(parseInt(DXWGStr.substr(i * 2, 2) || '0', 16))
				}
				readValue['DTemp'] = DTemps
				leftStr = leftStr.substring(2 * DXWGSize, leftStr.length)

				//MOS温感数量
				readValue['MOS'] = parseInt(leftStr.substr(0, 2) || '0', 16)
				leftStr = leftStr.substring(2, leftStr.length)
				
				//MOS温感温度
				let MOSTemps = []
				let MOSSize = readValue['MOS'] * 1
				let MOSStr = leftStr.substr(0, 2 * MOSSize)
				for (var i = 0; i < MOSSize; i++) {
					MOSTemps.push(parseInt(MOSStr.substr(i * 2, 2) || '0', 16))
				}
				readValue['MOSTemp'] = MOSTemps
				leftStr = leftStr.substring(2 * MOSSize, leftStr.length)
				
				//电池循环次数
				readValue['num'] = parseInt(this.reChangeStr(leftStr.substr(0, 4)) || '0', 16)
				leftStr = leftStr.substring(4, leftStr.length)
				
				//剩余电量
				readValue['RC'] = parseInt(this.reChangeStr(leftStr.substr(0, 4)) || '0', 16) * 0.1
				leftStr = leftStr.substring(4, leftStr.length)
				
				//电池满容量
				readValue['FCC'] = parseInt(this.reChangeStr(leftStr.substr(0, 4)) || '0', 16) * 0.1
				leftStr = leftStr.substring(4, leftStr.length)
				
				let vArray = this.hexToBitsFast(leftStr.substr(0,2)).split('').reverse();
				readValue['MOSCtrl'] = getMosState(vArray)
				console.log('readValue', readValue);
				break;
			case '11':
				//为电池组状态标志
				tempStatus = leftStr.substr(0, 8)
				for (var i = 0; i < 4; i++) {
					let bitStr = tempStatus.substr(i, 2);
					const vArray = this.hexToBitsFast(bitStr).split('').reverse();
					if (i === 0) {
						readValue['status1'] = getState1(vArray)
					}
					if (i === 1) {
						readValue['status2'] = getState2(vArray)
					}
					if (i === 2) {
						readValue['status3'] = getState3(vArray)
					}
					if (i === 3) {
						readValue['status4'] = getState4(vArray)
					}
				}
				leftStr = leftStr.substring(8, leftStr.length)
				
				//电流
				CurCadcStr = leftStr.substr(0, 4)
				readValue['CurCadc'] = parseInt(this.reChangeStr(CurCadcStr) || '0', 16) * 0.1
				leftStr = leftStr.substring(4, leftStr.length)
				
				//最高电压
				let VmaxStr = leftStr.substr(0, 4)
				readValue['Vmax'] = parseInt(this.reChangeStr(VmaxStr) || '0', 16) 
				leftStr = leftStr.substring(4, leftStr.length)
				
				//最低电压
				let VminStr = leftStr.substr(0, 4)
				readValue['Vmin'] = parseInt(this.reChangeStr(VminStr) || '0', 16)
				leftStr = leftStr.substring(4, leftStr.length)
				
				//总电压
				let VoltageStr = leftStr.substr(0, 4)
				readValue['Voltage'] = parseInt(this.reChangeStr(VoltageStr) || '0', 16) * 0.01
				leftStr = leftStr.substring(4, leftStr.length)
				
				//Tmax 最高电芯温度
				readValue['Tmax'] = parseInt(leftStr.substr(0, 2) || '0', 16)
				leftStr = leftStr.substring(2, leftStr.length)
				
				//Tmin 最低电芯温度
				readValue['Tmin'] = parseInt(leftStr.substr(0, 2) || '0', 16)
				leftStr = leftStr.substring(2, leftStr.length)
				
				
				//电池循环次数
				readValue['num'] = parseInt(this.reChangeStr(leftStr.substr(0, 4)) || '0', 16)
				leftStr = leftStr.substring(4, leftStr.length)
				
				//剩余电量
				readValue['RC'] = parseInt(this.reChangeStr(leftStr.substr(0, 4)) || '0', 16) * 0.1
				leftStr = leftStr.substring(4, leftStr.length)
				
				//电池满容量
				readValue['FCC'] = parseInt(this.reChangeStr(leftStr.substr(0, 4)) || '0', 16) * 0.1
				leftStr = leftStr.substring(4, leftStr.length)
				
				
				vArray = this.hexToBitsFast(leftStr.substr(0,2)).split('').reverse();
				readValue['MOSCtrl'] = getMosState(vArray)
				console.log('readValue', readValue);
				break;
			case '10':

				break;
			default:
				break;
		}
	}
	/**
	 * @param {Object} str 把 1234 变成 3412
	 */
	reChangeStr(str) {
		return str.slice(-2) + str.slice(0, str.length - 2);
	}

	/**
	 * 将十六进制字符串转换为二进制位字符串
	 * @param {string} hexStr - 十六进制字符串
	 * @returns {string} 二进制位字符串
	 */
	hexToBitsFast(hexStr) {
		const hexMap = {
			'0': '0000',
			'1': '0001',
			'2': '0010',
			'3': '0011',
			'4': '0100',
			'5': '0101',
			'6': '0110',
			'7': '0111',
			'8': '1000',
			'9': '1001',
			'a': '1010',
			'b': '1011',
			'c': '1100',
			'd': '1101',
			'e': '1110',
			'f': '1111'
		};
		return hexStr.toLowerCase().split('').map(c => hexMap[c] || '0000').join('');
	}

	/**
	 * 将字符串按指定大小分割
	 * @param {string} str - 字符串
	 * @param {number} size - 分割大小
	 * @returns {Array<string>} 分割后的字符串数组
	 */
	splitBySize(str, size) {
		const arr = [];
		for (let i = 0; i < str.length; i += size) {
			arr.push(str.slice(i, i + size));
		}
		return arr;
	}
}


export default new ProtocolManager();


function getMosState(binaryData) {
	const bitInfo = [{
			name: 'Bit0',
			value: binaryData[0],
			desc: '放电 MOS 强制断开'
		},
		{
			name: 'Bit1',
			value: binaryData[1],
			desc: '充电 MOS 强制断开'
		},
		{
			name: 'Bit2',
			value: binaryData[2],
			desc: '预放电 MOS 状态，1 表示开关闭合，允许预放电。'
		},
		{
			name: 'Bit3',
			value: binaryData[3],
			desc: '预充电 MOS 状态，1 表示开关闭合，允许预充电。'
		},
		{
			name: 'Bit4',
			value: binaryData[4],
			desc: '加热开关状态，1 表示开关闭合，允许加热。'
		},
		{
			name: 'Bit5',
			value: binaryData[5],
			desc: 'ACC 开关状态，1 表示开关闭合，允许闭合充放电 MOS。'
		},
		{
			name: 'Bit6',
			value: binaryData[6],
			desc: '充电开关状态，1 表示开关闭合，允许充电。'
		},
		{
			name: 'Bit7',
			value: binaryData[7],
			desc: '放电开关状态，1 表示开关闭合，允许放电。'
		},
	];
	return bitInfo;
}

function getState1(binaryData) {
	const bitInfo = [{
			name: 'Bit0',
			value: binaryData[0],
			desc: '充电中'
		},
		{
			name: 'Bit1',
			value: binaryData[1],
			desc: '充电过流'
		},
		{
			name: 'Bit2',
			value: binaryData[2],
			desc: ''
		},
		{
			name: 'Bit3',
			value: binaryData[3],
			desc: '充电 MOS 漏电'
		},
		{
			name: 'Bit4',
			value: binaryData[4],
			desc: '放电中'
		},
		{
			name: 'Bit5',
			value: binaryData[5],
			desc: '放电过流'
		},
		{
			name: 'Bit6',
			value: binaryData[6],
			desc: '放电短路'
		},
		{
			name: 'Bit7',
			value: binaryData[7],
			desc: '放电 MOS 漏电'
		},
	];
	return bitInfo;
}


function getState2(binaryData) {
	const bitInfo = [{
			name: 'Bit0',
			value: binaryData[0],
			desc: '电芯侦测线开路'
		},
		{
			name: 'Bit1',
			value: binaryData[1],
			desc: '温感侦测线开路'
		},
		{
			name: 'Bit2',
			value: binaryData[2],
			desc: 'MOS温感侦测线开路'
		},
		{
			name: 'Bit3',
			value: binaryData[3],
			desc: '模拟前端工作异常'
		},
		{
			name: 'Bit4',
			value: binaryData[4],
			desc: '电芯过压'
		},
		{
			name: 'Bit5',
			value: binaryData[5],
			desc: '电芯欠压'
		},
		{
			name: 'Bit6',
			value: binaryData[6],
			desc: '总压过高'
		},
		{
			name: 'Bit7',
			value: binaryData[7],
			desc: '总压过低'
		},
	];
	return bitInfo;
}

function getState3(binaryData) {
	const bitInfo = [{
			name: 'Bit0',
			value: binaryData[0],
			desc: 'MOS 温度超充放电温度上限'
		},
		{
			name: 'Bit1',
			value: binaryData[1],
			desc: 'MOS 温差超充放电温差上限'
		},
		{
			name: 'Bit2',
			value: binaryData[2],
			desc: 'MOS温感侦测线开路'
		},
		{
			name: 'Bit3',
			value: binaryData[3],
			desc: '电芯温度超过充电温度上限'
		},
		{
			name: 'Bit4',
			value: binaryData[4],
			desc: '电芯温度超过放电温度上限'
		},
		{
			name: 'Bit5',
			value: binaryData[5],
			desc: '电芯温度低于充电温度下限'
		},
		{
			name: 'Bit6',
			value: binaryData[6],
			desc: '电芯温度低于放电温度下限'
		},
		{
			name: 'Bit7',
			value: binaryData[7],
			desc: '电芯温差超过放电温度上限。'
		},
	];
	return bitInfo;
}

function getState4(binaryData) {
	const bitInfo = [{
			name: 'Bit0',
			value: binaryData[0],
			desc: '禁止充电'
		},
		{
			name: 'Bit1',
			value: binaryData[1],
			desc: '禁止放电'
		},
		{
			name: 'Bit2',
			value: binaryData[2],
			desc: ''
		},
		{
			name: 'Bit3',
			value: binaryData[3],
			desc: ''
		},
		{
			name: 'Bit4',
			value: binaryData[4],
			desc: ''
		},
		{
			name: 'Bit5',
			value: binaryData[5],
			desc: '压差高于充电允许压差上限'
		},
		{
			name: 'Bit6',
			value: binaryData[6],
			desc: '电芯电压低于充电电压下限'
		},
		{
			name: 'Bit7',
			value: binaryData[7],
			desc: '深度欠压'
		},
	];
	return bitInfo;
}